Move drawable clip tracking into GdkGC
authorAlexander Larsson <alexl@redhat.com>
Thu, 4 Dec 2008 19:18:02 +0000 (20:18 +0100)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:14:06 +0000 (10:14 +0200)
gdk/gdkgc.c
gdk/gdkinternals.h
gdk/gdkwindow.c
gdk/gdkwindow.h

index 6bc3a994ce4d4453dc948220e427d3dae34e65e1..355a346132059014c7444cb3c88204200e29ab4c 100644 (file)
@@ -43,6 +43,10 @@ struct _GdkGCPrivate
 {
   GdkRegion *clip_region;
 
+  guint32 region_tag_applied;
+  
+  GdkRegion *old_clip_region;
+  
   GdkSubwindowMode subwindow_mode;
   
   GdkFill fill;
@@ -190,6 +194,8 @@ gdk_gc_finalize (GObject *object)
 
   if (priv->clip_region)
     gdk_region_destroy (priv->clip_region);
+  if (priv->old_clip_region)
+    gdk_region_destroy (priv->old_clip_region);
   if (gc->colormap)
     g_object_unref (gc->colormap);
   if (priv->tile)
@@ -273,6 +279,12 @@ gdk_gc_set_values (GdkGC           *gc,
 
   priv = GDK_GC_GET_PRIVATE (gc);
 
+  if ((values_mask & GDK_GC_CLIP_X_ORIGIN) ||
+      (values_mask & GDK_GC_CLIP_Y_ORIGIN) ||
+      (values_mask & GDK_GC_CLIP_MASK) ||
+      (values_mask & GDK_GC_SUBWINDOW))
+    _gdk_gc_remove_drawable_clip (gc);
+  
   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
     gc->clip_x_origin = values->clip_x_origin;
   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
@@ -549,10 +561,10 @@ gdk_gc_set_clip_mask (GdkGC       *gc,
 }
 
 /* Takes ownership of passed in region */
-void
-_gdk_gc_set_clip_region_internal (GdkGC     *gc,
-                                 GdkRegion *region,
-                                 gboolean reset_origin)
+static void
+_gdk_gc_set_clip_region_real (GdkGC     *gc,
+                             GdkRegion *region,
+                             gboolean reset_origin)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
@@ -564,37 +576,54 @@ _gdk_gc_set_clip_region_internal (GdkGC     *gc,
   _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
 }
 
+/* Doesn't copy region, allows not to reset origin */
+void
+_gdk_gc_set_clip_region_internal (GdkGC     *gc,
+                                 GdkRegion *region,
+                                 gboolean reset_origin)
+{
+  _gdk_gc_remove_drawable_clip (gc);
+  _gdk_gc_set_clip_region_real (gc, region, reset_origin);
+}
+
+
 /* returns old clip region */
 void
-_gdk_gc_intersect_clip_region (GdkGC     *gc,
-                              GdkRegion *region,
-                              int        offset_x,
-                              int        offset_y,
-                              GdkRegion **old_clip_region)
+_gdk_gc_add_drawable_clip (GdkGC     *gc,
+                          guint32    region_tag,
+                          GdkRegion *region,
+                          int        offset_x,
+                          int        offset_y)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-  GdkRegion *old_clip;
-  gboolean free;
 
-  old_clip = priv->clip_region;
+  g_assert (priv->old_clip_region == NULL);
+  
+  priv->region_tag_applied = region_tag;
+  priv->old_clip_region = priv->clip_region;
 
   region = gdk_region_copy (region);
-
   if (offset_x != 0 || offset_y != 0)
     gdk_region_offset (region, offset_x, offset_y);
   
   priv->clip_region = region;
-  if (old_clip)
-    gdk_region_intersect (region, old_clip);
+  if (priv->old_clip_region)
+    gdk_region_intersect (region, priv->old_clip_region);
 
-  if (old_clip_region)
-    *old_clip_region = old_clip;
-  else
-    gdk_region_destroy (old_clip);
-  
   _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
-  
-  return old_clip;
+}
+
+void
+_gdk_gc_remove_drawable_clip (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  if (priv->region_tag_applied)
+    {
+      _gdk_gc_set_clip_region_real (gc, priv->old_clip_region, FALSE);
+      priv->old_clip_region = NULL;
+      priv->region_tag_applied = 0;
+    }
 }
 
 /**
@@ -614,12 +643,14 @@ gdk_gc_set_clip_rectangle (GdkGC              *gc,
   
   g_return_if_fail (GDK_IS_GC (gc));
 
+  _gdk_gc_remove_drawable_clip (gc);
+  
   if (rectangle)
     region = gdk_region_rectangle (rectangle);
   else
     region = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, region, TRUE);
+  _gdk_gc_set_clip_region_real (gc, region, TRUE);
 }
 
 /**
@@ -639,12 +670,14 @@ gdk_gc_set_clip_region (GdkGC           *gc,
 
   g_return_if_fail (GDK_IS_GC (gc));
 
+  _gdk_gc_remove_drawable_clip (gc);
+  
   if (region)
     copy = gdk_region_copy (region);
   else
     copy = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, copy, TRUE);
+  _gdk_gc_set_clip_region_real (gc, copy, TRUE);
 }
 
 /**
@@ -945,6 +978,16 @@ gdk_gc_copy (GdkGC *dst_gc,
     dst_priv->clip_region = gdk_region_copy (src_priv->clip_region);
   else
     dst_priv->clip_region = NULL;
+
+  dst_priv->region_tag_applied = src_priv->region_tag_applied;
+  
+  if (dst_priv->old_clip_region)
+    gdk_region_destroy (dst_priv->old_clip_region);
+
+  if (src_priv->old_clip_region)
+    dst_priv->old_clip_region = gdk_region_copy (src_priv->old_clip_region);
+  else
+    dst_priv->old_clip_region = NULL;
   
   dst_priv->fill = src_priv->fill;
   
index 995f3bf455cb6aae005ec991fc969396ffdf57fc..c9d537828dff0b10c149a797373f39b360b31c2c 100644 (file)
@@ -293,11 +293,12 @@ GdkPixmap *_gdk_gc_get_tile        (GdkGC *gc);
 GdkBitmap *_gdk_gc_get_stipple     (GdkGC *gc);
 guint32    _gdk_gc_get_fg_pixel    (GdkGC *gc);
 guint32    _gdk_gc_get_bg_pixel    (GdkGC *gc);
-void      _gdk_gc_intersect_clip_region     (GdkGC     *gc,
-                                            GdkRegion *region,
-                                            int        offset_x,
-                                            int        offset_y,
-                                            GdkRegion **old_region);
+void      _gdk_gc_add_drawable_clip     (GdkGC     *gc,
+                                        guint32    region_tag,
+                                        GdkRegion *region,
+                                        int        offset_x,
+                                        int        offset_y);
+void      _gdk_gc_remove_drawable_clip  (GdkGC     *gc);
 void       _gdk_gc_set_clip_region_internal (GdkGC     *gc,
                                             GdkRegion *region,
                                             gboolean reset_origin);
index 5d9b812a8075974d64b9c11ad718143f9619a420..7043b8385d7355a66dc3c807e7182e29302ca250 100644 (file)
@@ -69,6 +69,7 @@ struct _GdkWindowPaint
   gint y_offset;
   cairo_surface_t *surface;
   guint uses_implicit : 1;
+  guint32 region_tag;
 };
 
 /* Global info */
@@ -234,6 +235,14 @@ static gpointer parent_class = NULL;
 
 static const cairo_user_data_key_t gdk_window_cairo_key;
 
+static guint32
+new_region_tag (void)
+{
+  static guint32 tag = 0;
+
+  return ++tag;
+}
+
 GType
 gdk_window_object_get_type (void)
 {
@@ -509,6 +518,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
       if (private->clip_region)
        gdk_region_destroy (private->clip_region);
       private->clip_region = new_clip;
+      private->clip_tag = new_region_tag ();
 
       private->clip_region_with_children = gdk_region_copy (private->clip_region);
       remove_child_area (private, NULL, private->clip_region_with_children);
@@ -1925,17 +1935,19 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   implicit_paint = impl_window->implicit_paint;
 
   paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_copy (region);
+  paint->region_tag = new_region_tag ();
+      
   if (implicit_paint)
     {
       int width, height;
-
+      
       paint->uses_implicit = TRUE;
       paint->pixmap = g_object_ref (implicit_paint->pixmap);
       paint->x_offset = -private->abs_x + implicit_paint->x_offset;
       paint->y_offset = -private->abs_y + implicit_paint->y_offset;
-      paint->region = gdk_region_copy (region);
       gdk_region_intersect (paint->region, private->clip_region_with_children);
-
+      
       /* It would be nice if we had some cairo support here so we
         could set the clip rect on the cairo surface */
       width = private->abs_x + private->width;
@@ -1943,9 +1955,6 @@ gdk_window_begin_paint_region (GdkWindow       *window,
       
       paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
                                                            width, height);
-      if (paint->surface)
-       cairo_surface_set_device_offset (paint->surface,
-                                        - paint->x_offset, - paint->y_offset);
 
       /* Mark the region as valid on the implicit paint */
       gdk_region_offset (paint->region, private->abs_x, private->abs_y); 
@@ -1955,19 +1964,18 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   else
     {
       paint->uses_implicit = FALSE;
-      paint->region = gdk_region_copy (region);
       paint->x_offset = clip_box.x;
       paint->y_offset = clip_box.y;
       paint->pixmap =
        gdk_pixmap_new (window,
                        MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
-
       paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
-      cairo_surface_set_device_offset (paint->surface,
-                                      - paint->x_offset, - paint->y_offset);
     }
+  if (paint->surface)
+    cairo_surface_set_device_offset (paint->surface,
+                                    -paint->x_offset, -paint->y_offset);
   
-      
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *tmp_paint = list->data;
@@ -2264,8 +2272,7 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
 static void
 setup_clip_for_draw (GdkDrawable *drawable,
                     GdkGC *gc,
-                    int old_clip_x, int old_clip_y,
-                    GdkRegion **old_clip_region)
+                    int old_clip_x, int old_clip_y)
 {
   GdkWindowObject *private = (GdkWindowObject *)drawable;
   GdkRegion *clip;
@@ -2275,27 +2282,27 @@ setup_clip_for_draw (GdkDrawable *drawable,
   else
     clip = private->clip_region;
     
-  _gdk_gc_intersect_clip_region (gc, clip,
-                                /* If there was a clip origin set appart from the
-                                 * window offset, need to take that into consideration */
-                                -old_clip_x, -old_clip_y,
-                                old_clip_region);
+  _gdk_gc_add_drawable_clip (gc,
+                            private->clip_tag,
+                            clip,
+                            /* If there was a clip origin set appart from the
+                             * window offset, need to take that into consideration */
+                            -old_clip_x, -old_clip_y);
 }
 
 static void
 setup_clip_for_paint (GdkDrawable *drawable,
                      GdkWindowPaint *paint,
                      GdkGC *gc,
-                     int old_clip_x, int old_clip_y,
-                     GdkRegion **old_clip_region)
+                     int old_clip_x, int old_clip_y)
 {
-  _gdk_gc_intersect_clip_region (gc,
-                                /* This includes the window clip */
-                                paint->region,
-                                /* If there was a clip origin set appart from the
-                                 * window offset, need to take that into consideration */
-                                -old_clip_x, -old_clip_y,
-                                old_clip_region);
+  _gdk_gc_add_drawable_clip (gc,
+                            paint->region_tag,
+                            /* This includes the window clip */
+                            paint->region,
+                            /* If there was a clip origin set appart from the
+                             * window offset, need to take that into consideration */
+                            -old_clip_x, -old_clip_y);
 }
 
 
@@ -2322,23 +2329,21 @@ setup_clip_for_paint (GdkDrawable *drawable,
      }
 
 #define SETUP_PAINT_GC_CLIP(gc)                             \
-      GdkRegion *old_clip_region;                           \
       if (paint->uses_implicit)                                    \
        setup_clip_for_paint (drawable, paint, gc, old_clip_x,  \
-                              old_clip_y, &old_clip_region);
+                              old_clip_y);
 
 #define RESTORE_PAINT_GC_CLIP(gc)                          \
       if (paint->uses_implicit)                           \
-        _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+        _gdk_gc_remove_drawable_clip (gc);
 
 
 #define SETUP_DIRECT_GC_CLIP(gc)                            \
-      GdkRegion *old_clip_region;                           \
       gdk_window_flush_implicit_paint ((GdkWindow *)drawable);\
-      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y, &old_clip_region);
+      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
 
 #define RESTORE_DIRECT_GC_CLIP(gc)                                 \
-      _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+      _gdk_gc_remove_drawable_clip (gc);
 
 static GdkGC *
 gdk_window_create_gc (GdkDrawable     *drawable,
index ec3f67ac394a46994a6a1f6cc1e28afb3b36c089..7a628b58c74ed61243b7b1ddbcb2d5e3f18c21c7 100644 (file)
@@ -328,6 +328,7 @@ struct _GdkWindowObject
 
   int abs_x, abs_y; /* Absolute offset in impl */
   gint width, height;
+  guint32 clip_tag;
   GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
   GdkRegion *clip_region_with_children; /* Clip region in window coords */
   GdkColormap *colormap;